package com.gwaeron.game;

import java.awt.*;
import java.awt.image.*;
import java.util.StringTokenizer;

import com.golden.gamedev.object.*;
import com.golden.gamedev.object.background.abstraction.*;
import com.golden.gamedev.util.*;
import com.golden.gamedev.engine.*;

public class Map extends AbstractTileBackground {

	
	public static final int TILE_WIDTH = 32, TILE_HEIGHT = 32;
	public static final int GAME_WIDTH = 640, GAME_HEIGHT = 480;
	public static final int WIDTH_IN_TILES = GAME_WIDTH / TILE_WIDTH;
	public static final int HEIGHT_IN_TILES = GAME_HEIGHT / TILE_HEIGHT;

        Chipset chipsetLower;
        Chipset chipsetUpper;
        Chipset[] chipset;

        int[][] layer1; // the lower tiles
        int[][] layer2; // the fringe tiles
        ForegroundSprite[][] foreground; // Stuff to be drawn above the char
        int[][] foregroundLayer;
        RPGSprite[][] layer3; // the object/event/npc tiles
        int[][] levels;

        public Map(BaseLoader bsLoader, BaseIO bsIO, String mapName) {
                super(0, 0, TILE_WIDTH, TILE_HEIGHT);
                // Get number of rows/columns in the map background file, make layers
                // accordingly.
                int w = 0, h = 0;
                String[] lowerTile = FileUtil
                                .fileRead(bsIO.getStream(mapName + ".lwr"));
                StringTokenizer tk = new StringTokenizer(lowerTile[0]);
                while (tk.hasMoreTokens()) {
                        w++;
                        tk.nextToken();
                }
                h = lowerTile.length;
                layer1 = new int[w][h];
                layer2 = new int[w][h];
                layer3 = new RPGSprite[w][h];
                foreground = new ForegroundSprite[w][h];
                foregroundLayer = new int[w][h];
                levels = new int[w][h];
                lowerTile = FileUtil.fileRead(bsIO.getStream(mapName + ".lwr"));
                String[] upperTile = FileUtil
                                .fileRead(bsIO.getStream(mapName + ".upr"));
                String[] fg = FileUtil.fileRead(bsIO.getStream(mapName + ".for"));
                String[] lvls = FileUtil.fileRead(bsIO.getStream(mapName + ".lvl"));
                for (int j = 0; j < layer1[0].length; j++) {
                        StringTokenizer lowerToken = new StringTokenizer(lowerTile[j]);
                        StringTokenizer upperToken = new StringTokenizer(upperTile[j]);
                        StringTokenizer fgToken = new StringTokenizer(fg[j]);
                        StringTokenizer lvlToken = new StringTokenizer(lvls[j]);
                        for (int i = 0; i < layer1.length; i++) {
                                layer1[i][j] = Integer.parseInt(lowerToken.nextToken());
                                layer2[i][j] = Integer.parseInt(upperToken.nextToken());
                                foregroundLayer[i][j] = Integer.parseInt(fgToken.nextToken());
                                levels[i][j] = Integer.parseInt(lvlToken.nextToken());
                        }
                }

                // set the actual map size based on the read file
                setSize(layer1.length, layer1[0].length);

                chipsetLower = new Chipset(bsLoader.getImages("ChipSet2.png", 6, 24,
                                false));
                chipsetUpper = new Chipset(bsLoader.getImages("ChipSet3.png", 6, 24));
                for (int i = 0; i < foregroundLayer.length; i++) {
                        for (int j = 0; j < foregroundLayer[0].length; j++) {
                                if (foregroundLayer[i][j] != -1)
                                        foreground[i][j] = new ForegroundSprite(
                                                        chipsetUpper.image[foregroundLayer[i][j]], i, j);
                        }
                }
                chipset = new Chipset[16];
                BufferedImage[] image = bsLoader.getImages("ChipSet1.png", 4, 4, false);
                int[] chipnum = new int[] { 0, 1, 4, 5, 8, 9, 11, 12, 2, 3, 6, 7, 10,
                                11, 14, 15 };
                for (int i = 0; i < chipset.length; i++) {
                        int num = chipnum[i];
                        BufferedImage[] chips = ImageUtil.splitImages(image[num], 3, 4);
                        chipset[i] = new Chipset(chips);
                }
        }

        public ForegroundSprite[][] getForeground() {
                return this.foreground;
        }

        public void renderTile(Graphics2D g, int tileX, int tileY, int x, int y) {
                // render layer 1
                int tilenum = layer1[tileX][tileY];
                if (tilenum < chipsetLower.image.length) {
                        g.drawImage(chipsetLower.image[tilenum], x, y, null);

                } else if (tilenum >= chipsetLower.image.length) {
                        BufferedImage image = chipset[tilenum - chipsetLower.image.length].image[2];
                        g.drawImage(image, x, y, null);
                }

                // render layer 2
                int tilenum2 = layer2[tileX][tileY];
                if (tilenum2 != -1 && tilenum2 != -2) {
                        g.drawImage(chipsetUpper.image[tilenum2], x, y, null);
                }

                // layer 3 is rendered by sprite group
                // Foreground layer is rendered by sprite group, too.

        }

        public boolean isOccupied(int tileX, int tileY) {
                if (layer2[tileX][tileY] == -2)
                        return false;
                try {
                        return (layer2[tileX][tileY] != -1 || // there's a foreground tile
                        layer3[tileX][tileY] != null); // there's a character
                } catch (Exception e) {
                        // out of bounds
                        return true;
                }
        }

        public RPGSprite getLayer3(int tileX, int tileY) {
                try {
                        return layer3[tileX][tileY];
                } catch (Exception e) {
                        // out of bounds
                        return null;
                }
        }

        // chipset is only a pack of images
        class Chipset {
                BufferedImage[] image;

                public Chipset(BufferedImage[] image) {
                        this.image = image;
                }

        }

        public String nextZone(int tileX, int tileY) {
                // TODO Auto-generated method stub
                return "downtown";
        }

        public boolean isZoneEdge(int tileX, int tileY) {
                if (layer2[tileX][tileY] == -2)
                        return true;
                return false;
        }

        public int[][] getLevels() {
                return this.levels;
        }

}